"""
    命名空间是名称到对象的映射，当前大部分命名空间都是通过python字典来实现的。
    它的主要作用是避免项目中的名字冲突，每一个命名空间都是相对独立的，在不同的
    命名空间可以同名，在相同的命名空间中不可以同名。

    命名空间分类：
    内置：主要用来存放内置函数、异常等。比如abs函数、BaseException异常
    全局：指在模块中定义的名称。比如：类、函数等。
    局部：指在函数中定义的名称，比如：函数的参数，在函数中定义的变量等。

    生命周期：
        通常在不同时创建的命名空间拥有不同的生命周期，看一下三种命名空间的生命周期：
        * 内置：在Python解释器启动的时候创建，退出时销毁
        * 全局：在模块定义被读入时创建，在python解释器退出时销毁。
        * 局部：对于类，在python解释器读到定义时创建，类定义结束后销毁；对于函数，在函数调用时创建创建，函数执行完成或出现未捕获异常时销毁。

    作用域：
        作用域是 Python 程序可以直接访问命名空间的文本区域（代码区域），名称的非限定引用会尝试在命名空间中查找名称，作用域是静态的，
        命名空间是随着解释器的执行动态产生的，因此在作用域中访问命名空间中的名字具有了动态性，即作用域被静态确定，被动态使用。
    四种作用域；
        局部：最先被搜索的最内部作用域，包含局部名称。
        嵌套：根据嵌套层次由内向外搜索，包含非全局、非局部名称。
        全局：倒数第二个被搜索，包含当前模块的全局名称。
        内建：最后被搜索，包含内置名称的命名空间。

"""
# 全局作用域
g = 1
def outer():
    # 嵌套作用域
    e = 2
    def inner():
        # 局部作用域
        i = 3


"""
    global & nonlocal
    全局变量：定义在函数外部的变量。
    局部变量：定义在函数内部的变量。

"""

# 全局变量
d = 0
def sub(a, b):
    # 使用 global 声明 d 为全局变量
    global d
    d = a - b
    print('函数内 : ', d)

sub(9, 1) # 内部影响外部
print('函数外 : ', d)


"""
    当内部作用域想要修改外部作用域的变量时，就要用到 global 和 nonlocal 关键字了，下面通过具体示例来了解一下。
    如果需要修改嵌套作用域中的变量，则需用到 nonlocal 关键字。
"""
def outer2():
    d = 1
    def inner():
        nonlocal d
        d = "222222222222222222222"
        print('inner：', d)
    inner()
    print('outer：', d)
outer2()
print("d: ", d)

"""
    global 是用于定义了全局变量的情况，局部使用全局变量，在局部进行声明
    nonlocal 非局部，可以访问切套外层的变量，修改对应的值。官方解释：用于在嵌套函数中，声明某个变量是外层函数作用域中的变量，这样可以在内层函数中对其进行修改。
    有没有外部可以修改局部的关键字呢？
"""
